package role

import (
	"cgs-server/server"
	"cgs-server/server/base"
	"cgs-server/server/model"
	"cgs-server/server/system/authority"
	"cgs-server/server/system/role_authority"
	"cgs-server/server/system/user_role"
	"errors"
	"fmt"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

type RoleService interface {
	base.Service
	// 根据多个角色 id 获取角色列表
	ListByIds(ids []primitive.ObjectID, mdl *model.DataUserModel) (*model.Roles, error)
	// 根据 角色 id 查找角色
	GetByRoleId(mdl *model.DataUserModel) (*model.Role, error)

	// 更新角色的用户
	UpdateUser(mdl *model.DataUserModel) error

	CountUserByRoleId(roleId string) (int64, error)

	// 根据 visualId 删除
	RemoveByVisualId(mdl *model.DataUserModel) error

	// 查询某个应用的应用角色
	CheckAppRoleByVisualId(mdl *model.DataUserModel) error

	FindVisualByVisualId(visualId string, visualType string) (*model.Visual, error)
}

func NewRoleService() RoleService {
	roleRepo := NewRoleRepository()
	return &roleService{
		roleRepo:     roleRepo,
		roleAuthRepo: role_authority.NewRoleAuthorityRepository(),
		roleUserRepo: user_role.NewUserRoleRepository(),
		ServiceImpl:  base.ServiceImpl{Repo: roleRepo},
	}
}

type roleService struct {
	roleRepo     RoleRepository
	roleAuthRepo role_authority.RoleAuthorityRepository
	roleUserRepo user_role.UserRoleRepository
	base.ServiceImpl
}

func (r *roleService) FindVisualByVisualId(visualId string, visualType string) (*model.Visual, error) {
	hex, err := primitive.ObjectIDFromHex(visualId)
	if err != nil {
		return nil, err
	}
	res, err := r.roleRepo.FindVisualByVisualId(hex, visualType)
	if err != nil {
		return nil, err
	}
	return res, nil
}

func (r *roleService) Init(name ...string) error {
	err := r.roleRepo.InitDB()
	if err != nil {
		return err
	}
	err = r.roleAuthRepo.InitDB()
	return err
}

// 新增角色
func (r *roleService) Save(mdl *model.DataUserModel) error {
	// 不允许添加 Administrator 角色
	if role, ok := mdl.Data.(*model.Role); ok {
		if role.Type == "" {
			return errors.New("role type is empty")
		}
		// 如果添加管理员角色需要验证是否已经存在
		if role.RoleAlias == "AppAdministrator" && role.Type == model.AppRole && role.VisualId == "" {
			return errors.New("VisualId is required")
		}
		if role.RoleAlias == "Administrator" || role.RoleAlias == "AppAdministrator" {
			result, err := r.roleRepo.FindByRoleAliasOrName(mdl)
			if err != nil {
				return err
			}
			if result != nil {
				return fmt.Errorf("RoleAlias '%s' is already exist.", result.RoleAlias)
			}
		}
		// 角色名称允许重复

		// 新增角色
		err := r.roleRepo.Insert(mdl)
		if err != nil {
			return err
		}
		// todo 新增 角色权限关联信息 后台权限或者应用权限
		if role.Type == model.BackRole {
			if role.Authorities != nil {
				err = r.roleAuthRepo.UpdateByRoleId(role)
			}
		} else if role.Type == model.AppRole {
			if role.AppAuths != nil {
				err = r.roleAuthRepo.UpdateByRoleId(role)
			}
		} else {
			return errors.New("role type must be 'APP_ROLE' or 'BACK_ROLE'")
		}
		return err
	} else {
		return errors.New("Role type error.")
	}
}

func (r *roleService) UpdateUser(mdl *model.DataUserModel) error {
	if role, ok := mdl.Data.(*model.Role); ok {
		return r.roleUserRepo.UpdateByRole(role)
	} else {
		return errors.New("Role type error")
	}
}

// 根据多个 roleId 获取列表
func (r *roleService) ListByIds(ids []primitive.ObjectID, mdl *model.DataUserModel) (*model.Roles, error) {
	roles, err := r.roleRepo.ListByIds(ids, mdl)
	if err != nil {
		return nil, err
	}
	for _, role := range *roles {
		// 应用角色的权限
		if role.VisualId == "" {
			return nil, fmt.Errorf("Role '%v''s visualId is empty.", role.VisualId)
		}
		if role.RoleAlias == "AppAdministrator" {
			// 是应用管理员，拥有此应用的所有权限
			appAuths := server.GetAllAppAuth()
			auths := []string{string(server.ManageAppAuth)}
			for i := range appAuths {
				auths = append(auths, appAuths[i].Name)
			}
			role.AppAuths = auths
		} else {
			// 应用角色的权限
			auths, err := r.roleAuthRepo.FindByRoleId(role.Id)
			if err != nil {
				return nil, err
			}
			role.AppAuths = auths.GetAuths()
			role.FormAuths = auths.GetFormAuths()
		}
	}
	return roles, nil
}

func (r *roleService) GetByRoleId(mdl *model.DataUserModel) (*model.Role, error) {
	if role, ok := mdl.Data.(*model.Role); ok {
		visualType := role.VisualType
		roleRes, err := r.roleRepo.GetById(mdl)
		if err != nil {
			return nil, err
		}
		if roleRes == nil {
			return nil, errors.New("Role not found")
		}
		if roleRes.Type == model.BackRole {
			// todo 这里再加一个判断，用来区分租户管理员(超级管理员)和普通管理员的权限
			if roleRes.RoleAlias == "Administrator" || roleRes.RoleAlias == "AppAdministrator" {
				authService := authority.NewAuthorityService()
				res, err := authService.List(&model.DataUserModel{
					Data: nil,
					User: mdl.User,
				})
				if err != nil {
					return nil, err
				}
				auths := res.([]server.AuthorityModel)
				for k := range auths {
					if roleRes.RoleAlias == "AppAdministrator" && auths[k].ID == string(server.ManageBackend) {
						continue
					}
					roleRes.Authorities = append(roleRes.Authorities, auths[k].ID)
				}
				if roleRes.IsInitial || roleRes.TenantId == "000000" {
					roleRes.Authorities = append(roleRes.Authorities, string(server.ManageLicence))
				}

			} else {
				auths, err := r.roleAuthRepo.FindByRoleId(role.Id)
				if err != nil {
					return nil, err
				}
				roleRes.Authorities = auths.GetAuths()
			}
			// 查询用户数
			userSize, err := r.CountUserByRoleId(role.Id.Hex())
			if err != nil {
				return nil, err
			}
			roleRes.UserSize = userSize
		} else if roleRes.Type == model.AppRole {
			if roleRes.RoleAlias == "AppAdministrator" {
				// 是应用管理员，拥有此应用的所有权限
				appAuths := server.GetAllAppAuth()
				auths := []string{string(server.ManageAppAuth)}
				for i := range appAuths {
					auths = append(auths, appAuths[i].Name)
				}
				roleRes.AppAuths = auths
			} else {
				// 应用角色的权限
				auths, err := r.roleAuthRepo.FindByRoleId(role.Id)
				if err != nil {
					return nil, err
				}
				roleRes.AppAuths = auths.GetAuths()
				roleRes.FormAuths = auths.GetFormAuths()
			}
			// 应用角色的用户
			userRoles, err := r.roleUserRepo.FindByRoleId(role.Id)
			if err != nil {
				return nil, err
			}
			roleRes.UserIds = userRoles.GetUsers()
			roleRes.UserSize = int64(len(roleRes.UserIds))

			// 根据 userIds 数组查询用户列表
			users, err := r.roleRepo.FindUserByIds(userRoles.GetUserBsonIds())
			if err != nil {
				return nil, err
			}
			// 查询单个视图
			visualId, err := primitive.ObjectIDFromHex(roleRes.VisualId)
			if err != nil {
				return nil, err
			}
			vs, err := r.roleRepo.FindVisualByVisualId(visualId, visualType)
			if err != nil {
				return nil, err
			}
			if vs == nil {
				return nil, model.NotFoundError("visual")
			}
			for i := range users {
				if users[i].UserId.Hex() == vs.Owner {
					users[i].IsOwner = true
					break
				}
			}
			roleRes.Users = users
		}
		return roleRes, nil
	} else {
		return nil, errors.New("Role type error")
	}
}

func (r *roleService) List(mdl *model.DataUserModel) (interface{}, error) {
	if role, ok := mdl.Data.(*model.Role); ok {
		res, err := r.roleRepo.Find(mdl)
		var roleRes = res.(*model.Roles)
		//childRoleRes := model.Roles{}
		visualType := role.VisualType
		if role.Type == model.BackRole {
			// 查询用户数
			for _, role := range *roleRes {
				userSize, err := r.CountUserByRoleId(role.Id.Hex())
				if err != nil {
					return nil, err
				}
				role.UserSize = userSize
			}
		} else if role.Type == model.AppRole {
			// 查询应用角色下的用户信息
			for _, role := range *roleRes {
				userRoles, err := r.roleUserRepo.FindByRoleId(role.Id)
				if err != nil {
					return nil, err
				}
				role.UserIds = userRoles.GetUsers()
				role.UserSize = int64(len(role.UserIds))

				// 根据 userIds 数组查询用户列表
				users, err := r.roleRepo.FindUserByIds(userRoles.GetUserBsonIds())
				if err != nil {
					return nil, err
				}
				// 查询单个视图
				visualId, err := primitive.ObjectIDFromHex(role.VisualId)
				if err != nil {
					return nil, err
				}
				vs, err := r.roleRepo.FindVisualByVisualId(visualId, visualType)
				if err != nil {
					return nil, err
				}
				for i := range users {
					if users[i].UserId.Hex() == vs.Owner {
						users[i].IsOwner = true
						break
					}
				}
				role.Users = users
			}
		}

		//roleList := model.RolesToWeb{}
		//for _,value := range *roleRes{
		//	if value.ParentId == "0"{
		//		role := model.RoleToWeb{
		//			NodeId: value.NodeId,
		//			RoleName: value.RoleName,
		//			RoleId: value.RoleAlias,
		//		}
		//		roleList = append(roleList, &role)
		//	} else if value.ParentId == "" {
		//		value.ParentId = "0"
		//		role := model.RoleToWeb{
		//			NodeId: value.NodeId,
		//			RoleName: value.RoleName,
		//			RoleId: value.RoleAlias,
		//
		//		}
		//		roleList = append(roleList, &role)
		//	} else {
		//		childRoleRes = append(childRoleRes, value)
		//	}
		//}

		//r.creatRoleListToWeb(&roleList, childRoleRes)

		return roleRes, err
	} else {
		return nil, errors.New("Role type error")
	}

}

//递归遍历剩余未找到父亲的角色
func (r *roleService) creatRoleListToWeb(roleList *model.RolesToWeb, child model.Roles) {

	if len(child) == 0 {
		return
	}

	flag := false
	for i, childValue := range child {
		for _, rootValue := range *roleList {
			if childValue.ParentId == rootValue.RoleId {
				var role = model.RoleToWeb{
					Id:       childValue.Id,
					RoleName: childValue.RoleName,
					RoleId:   childValue.RoleAlias,
				}
				rootValue.Children = append(rootValue.Children, &role)
				child = append(child[:i], child[i+1:]...)
				flag = true
				break
			} else if r.findParent(rootValue.Children, childValue) {
				child = append(child[:i], child[i+1:]...)
				flag = true
				break
			}
		}
		if flag {
			break
		}
	}

	r.creatRoleListToWeb(roleList, child)
}

//判断该角色是否在另一个角色的children内，递归遍历另一个角色children中所有的角色
func (r *roleService) findParent(roleList []*model.RoleToWeb, child *model.Role) bool {
	flag := false
	for _, rootValue := range roleList {
		if rootValue.RoleId == child.ParentId {
			var role = model.RoleToWeb{
				Id:       child.Id,
				RoleName: child.RoleName,
				RoleId:   child.RoleAlias,
			}
			rootValue.Children = append(rootValue.Children, &role)
			return true
		} else if r.findParent(rootValue.Children, child) {
			flag = true
		}
	}

	return flag
}

func (r *roleService) Update(mdl *model.DataUserModel) error {
	// 1. 更新角色表
	// 2. 更新角色权限表
	if role, ok := mdl.Data.(*model.Role); ok {
		// 查询角色信息
		roleRes, err := r.roleRepo.GetById(mdl)
		if err != nil {
			return err
		}
		if roleRes == nil {
			return errors.New("Role is not exist.")
		}
		if roleRes.RoleAlias == "Administrator" || roleRes.RoleAlias == "AppAdministrator" {
			return errors.New("Not allowed to update 'Administrator' or 'AppAdministrator' role!")
		}
		// 同一租户下，角色英文名称不允许重复
		// 根据角色英文名称查询
		/*result, err := r.roleRepo.FindByRoleAlias(mdl)
		if err != nil {
			return err
		}
		if result != nil {
			if result.NodeId != role.NodeId {
				return fmt.Errorf("RoleAlias '%s' is already exist.", result.RoleAlias)
			}
		}*/
		// 更新角色
		err = r.roleRepo.Update(mdl)
		if err != nil {
			return err
		}
		// 更新 角色权限关联信息
		if role.Type == model.BackRole {
			if role.Authorities != nil {
				err = r.roleAuthRepo.UpdateByRoleId(role)
			}
		} else if role.Type == model.AppRole {
			if role.AppAuths != nil {
				err = r.roleAuthRepo.UpdateByRoleId(role)
			}
		} else {
			return errors.New("role type must be 'APP_ROLE' or 'BACK_ROLE'")
		}
		return err
	} else {
		return errors.New("Role type error.")
	}
}

func (r *roleService) RemoveLogic(mdl *model.DataUserModel) error {
	if role, ok := mdl.Data.(*model.Role); ok {
		// 1. 逻辑删除角色信息
		err := r.roleRepo.DeleteLogic(mdl)
		if err != nil {
			return err
		}
		// 2. 删除角色权限关联信息
		err = r.roleAuthRepo.DeleteByRoleId(role.Id)
		return err
	} else {
		return errors.New("Role type error.")
	}
}

// 删除角色及其子角色
func (r *roleService) Remove(mdl *model.DataUserModel) error {
	if role, ok := mdl.Data.(*model.Role); ok {
		// 查询角色信息
		roleRes, err := r.roleRepo.GetById(mdl)
		if err != nil {
			return err
		}
		if roleRes == nil {
			return errors.New("Role is not exist.")
		}
		if roleRes.RoleAlias == "Administrator" || roleRes.RoleAlias == "AppAdministrator" {
			return errors.New("Not allowed to delete 'Administrator' or 'AppAdministrator' role!")
		}
		// 1. 删除角色信息
		err = r.roleRepo.Delete(mdl)
		if err != nil {
			return err
		}
		// 2. 删除角色权限关联信息
		err = r.roleAuthRepo.DeleteByRoleId(role.Id)
		if err != nil {
			return err
		}
		// 3. 删除用户角色关联表
		err = r.roleUserRepo.DeleteByRoleId(role.Id.Hex())
		return err
		// todo 3. 或许需要更新拥有此角色的用户的信息
	} else {
		return errors.New("Role type error.")
	}
}

func (r *roleService) RemoveByVisualId(mdl *model.DataUserModel) error {
	if role, ok := mdl.Data.(*model.Role); ok {
		if role.VisualId == "" {
			return errors.New("VisualId is required.")
		}
		// 查询该应用下的所有角色，全部删除
		role.Type = model.AppRole
		list, err := r.roleRepo.Find(mdl)
		if err != nil {
			return err
		}
		if list == nil {
			return nil
		}
		roleList := list.(*model.Roles)

		// 1. 删除角色信息
		mdl.Filter = &bson.M{
			"visualId": role.VisualId,
		}
		err = r.roleRepo.BatchDelete(mdl)
		if err != nil {
			return err
		}
		// 2. 删除角色权限关联信息
		ids := []string{}
		for i := range *roleList {
			ids = append(ids, (*roleList)[i].Id.Hex())
		}
		err = r.roleAuthRepo.BatchDeleteByRoleIds(ids)
		if err != nil {
			return err
		}
		// 3. 删除用户角色关联表
		err = r.roleUserRepo.BatchDeleteByRoleIds(ids)
		return err
		// todo 3. 或许需要更新拥有此角色的用户的信息
	} else {
		return model.NewTypeError("role")
	}
}

func (r *roleService) CountUserByRoleId(roleId string) (int64, error) {
	return r.roleRepo.CountUser(roleId)
}

func (r *roleService) CheckAppRoleByVisualId(mdl *model.DataUserModel) error {
	if role, ok := mdl.Data.(*model.Role); ok {
		mdl.Filter = &bson.M{
			"visualId":  role.VisualId,
			"roleAlias": "AppAdministrator",
		}
		one, err := r.roleRepo.FindOne(mdl)
		if err != nil {
			return err
		}
		if one != nil {
			roleRes := one.(*model.Role)
			// 检查用户
			findOne, _ := r.roleUserRepo.FindOne(&model.DataUserModel{
				Data: &model.UserRole{
					UserId: role.UserId,
					RoleId: roleRes.Id.Hex(),
				},
				User: nil,
			})
			if findOne == nil {
				// 没有找到，新增一个用户
				roleRes.UserIds = []string{role.UserId}
				err := r.roleUserRepo.UpdateByRole(roleRes)
				return err
			}
		} else {
			// 新增一个应用角色
			roleModel := &model.Role{
				RoleName:  "应用管理员",
				ParentId:  "0",
				Sort:      new(int),
				RoleAlias: "AppAdministrator",
				Desc:      "可以配置应用，管理应用下所有数据和人员",
				Type:      model.AppRole,
				VisualId:  role.VisualId,
			}
			err := r.Save(&model.DataUserModel{
				Data: roleModel,
				User: mdl.User,
			})
			if err != nil {
				return err
			}
			// 新增一个用户
			roleModel.UserIds = []string{role.UserId}
			err = r.roleUserRepo.UpdateByRole(roleModel)
			return err
		}
		return nil
	} else {
		return model.NewTypeError("role")
	}
}
